package net.sourceforge.jweb.util;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class AutoBoxingUtil {
	private AutoBoxingUtil() {
	}

	private static Map<String, Object> primaryTypeDefaults = new HashMap<String, Object>();
	private static Map<String, Object> supportedBoxingTypeDefaults = new HashMap<String, Object>();
	static {
		/* 八种基本数据类型 */
		primaryTypeDefaults.put("boolean", new Boolean(false));
		primaryTypeDefaults.put("byte", new Byte((byte) 0));
		primaryTypeDefaults.put("char", new Character(' '));
		primaryTypeDefaults.put("int", new Integer(0));
		primaryTypeDefaults.put("short", new Short((short) 0));
		primaryTypeDefaults.put("long", new Long(0l));
		primaryTypeDefaults.put("float", new Float(0f));
		primaryTypeDefaults.put("double", new Double(0d));

		/* 八种基本数据类型和装箱类 */
		supportedBoxingTypeDefaults.putAll(primaryTypeDefaults);
		supportedBoxingTypeDefaults.put("java.lang.Boolean", null);
		supportedBoxingTypeDefaults.put("java.lang.Byte", null);
		supportedBoxingTypeDefaults.put("java.lang.Character", null);
		supportedBoxingTypeDefaults.put("java.lang.Integer", null);
		supportedBoxingTypeDefaults.put("java.lang.Short", null);
		supportedBoxingTypeDefaults.put("java.lang.Long", null);
		supportedBoxingTypeDefaults.put("java.lang.Float", null);
		supportedBoxingTypeDefaults.put("java.lang.Double", null);

		/* 八种基本数据类型的数组 */
		supportedBoxingTypeDefaults.put("[Z", null);
		supportedBoxingTypeDefaults.put("[B", null);
		supportedBoxingTypeDefaults.put("[C", null);
		supportedBoxingTypeDefaults.put("[I", null);
		supportedBoxingTypeDefaults.put("[S", null);
		supportedBoxingTypeDefaults.put("[J", null);
		supportedBoxingTypeDefaults.put("[F", null);
		supportedBoxingTypeDefaults.put("[D", null);

		/* 八种基本数据类型的装箱类型的数组 */
		supportedBoxingTypeDefaults.put("[Ljava.lang.Boolean;", null);
		supportedBoxingTypeDefaults.put("[Ljava.lang.Byte;", null);
		supportedBoxingTypeDefaults.put("[Ljava.lang.Character;", null);
		supportedBoxingTypeDefaults.put("[Ljava.lang.Integer;", null);
		supportedBoxingTypeDefaults.put("[Ljava.lang.Short;", null);
		supportedBoxingTypeDefaults.put("[Ljava.lang.Long;", null);
		supportedBoxingTypeDefaults.put("[Ljava.lang.Float;", null);
		supportedBoxingTypeDefaults.put("[Ljava.lang.Double;", null);

		supportedBoxingTypeDefaults.put("java.lang.String", null);
		supportedBoxingTypeDefaults.put("[Ljava.lang.String;", null);

		supportedBoxingTypeDefaults.put("java.util.Date", null);
		supportedBoxingTypeDefaults.put("[Ljava.util.Date;", null);
	}

	public static boolean isSupportedBoxType(Class<?> c) {
		return supportedBoxingTypeDefaults.containsKey(c.getClass().getName());
	}

	public static Object getPrimaryDefaultValue(String primary) {
		return primaryTypeDefaults.get(primary);
	}

	public static boolean isPrimary(Field f) {
		return primaryTypeDefaults.keySet().contains(f.getClass().getName());
	}

	public static Object box(String clazz, String[] valStr, String dateFormat) {
		if (valStr == null)
			return null;

		/* 八种基本数据类型和装箱类 */
		if ("boolean".equals(clazz) || "java.lang.Boolean".equals(clazz))
			return richBoolean(valStr[0]);
		if ("byte".equals(clazz) || "java.lang.Byte".equals(clazz))
			return Byte.valueOf(valStr[0]);
		if ("char".equals(clazz) || "java.lang.Character".equals(clazz))
			return Character.valueOf(valStr[0].length() == 0 ? ' ' : valStr[0].charAt(0));
		if ("int".equals(clazz) || "java.lang.Integer".equals(clazz))
			return Integer.parseInt(valStr[0]);
		if ("short".equals(clazz) || "java.lang.Short".equals(clazz))
			return Short.valueOf(valStr[0]);
		if ("long".equals(clazz) || "java.lang.Long".equals(clazz))
			return Long.valueOf(valStr[0]);
		if ("float".equals(clazz) || "java.lang.Float".equals(clazz))
			return Float.valueOf(valStr[0]);
		if ("double".equals(clazz) || "java.lang.Double".equals(clazz))
			return Double.valueOf(valStr[0]);

		/* 八种基本数据类型的数组 */
		if ("[Z".equals(clazz))
			return getPrimiryBoolArray(valStr);
		if ("[B".equals(clazz))
			return getPrimiryByteArray(valStr);
		if ("[C".equals(clazz))
			return getPrimiryCharArray(valStr);
		if ("[I".equals(clazz))
			return getPrimiryIntArray(valStr);
		if ("[S".equals(clazz))
			return getPrimiryShortArray(valStr);
		if ("[J".equals(clazz))
			return getPrimiryLongArray(valStr);
		if ("[F".equals(clazz))
			return getPrimiryFloatArray(valStr);
		if ("[D".equals(clazz))
			return getPrimiryDoubleArray(valStr);

		/* 八种基本数据类型的装箱类型的数组 */
		if ("[Ljava.lang.Boolean;".equals(clazz))
			return getBoolArray(valStr);
		if ("[Ljava.lang.Byte;".equals(clazz))
			return getByteArray(valStr);
		if ("[Ljava.lang.Character;".equals(clazz))
			return getCharArray(valStr);
		if ("[Ljava.lang.Integer;".equals(clazz))
			return getIntArray(valStr);
		if ("[Ljava.lang.Short;".equals(clazz))
			return getShortArray(valStr);
		if ("[Ljava.lang.Long;".equals(clazz))
			return getLongArray(valStr);
		if ("[Ljava.lang.Float;".equals(clazz))
			return getFloatArray(valStr);
		if ("[Ljava.lang.Double;".equals(clazz))
			return getDoubleArray(valStr);

		/* String */
		if ("java.lang.String".equals(clazz))
			return valStr[0];

		/* String 数组 */
		if ("[Ljava.lang.String;".equals(clazz))
			return valStr;

		/* 日期 */
		if ("java.util.Date".equals(clazz))
			return getDate(valStr[0], dateFormat);

		/* 日期数组 */
		if ("[Ljava.util.Date;".equals(clazz))
			return getDateArray(valStr, dateFormat);

		/* java.util.Calendar日历 */

		/* java.util.Calendar日历数组 */

		/* java.util.Collection支持 */

		return null;
	}

	private static Date[] getDateArray(String[] valStr, String dateFormat) {
		Date[] dates = new Date[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			dates[i] = getDate(valStr[i], dateFormat);
		return dates;
	}

	private static Date getDate(String string, String dateFormat) {
		try {
			Date date = new SimpleDateFormat(dateFormat).parse(string);
			return date;
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	private static float[] getPrimiryFloatArray(String[] valStr) {
		float[] floats = new float[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			floats[i] = Float.valueOf(valStr[i]).floatValue();
		return floats;
	}

	private static Float[] getFloatArray(String[] valStr) {
		Float[] floats = new Float[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			floats[i] = Float.valueOf(valStr[i]);
		return floats;
	}

	private static double[] getPrimiryDoubleArray(String[] valStr) {
		double[] doubles = new double[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			doubles[i] = Double.valueOf(valStr[i]).doubleValue();
		return doubles;
	}

	private static Double[] getDoubleArray(String[] valStr) {
		Double[] doubles = new Double[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			doubles[i] = Double.valueOf(valStr[i]);
		return doubles;
	}

	private static long[] getPrimiryLongArray(String[] valStr) {
		long longs[] = new long[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			longs[i] = Long.valueOf(valStr[i]).longValue();
		return longs;
	}

	private static Long[] getLongArray(String[] valStr) {
		Long longs[] = new Long[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			longs[i] = Long.valueOf(valStr[i]);
		return longs;
	}

	private static short[] getPrimiryShortArray(String[] valStr) {
		short[] shorts = new short[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			shorts[i] = Short.valueOf(valStr[i]).shortValue();
		return shorts;
	}

	private static Object getShortArray(String[] valStr) {
		Short[] shorts = new Short[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			shorts[i] = Short.valueOf(valStr[i]);
		return shorts;
	}

	private static int[] getPrimiryIntArray(String[] valStr) {
		int integer[] = new int[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			integer[i] = Integer.valueOf(valStr[i]).intValue();
		return integer;
	}

	private static Integer[] getIntArray(String[] valStr) {
		Integer integer[] = new Integer[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			integer[i] = Integer.valueOf(valStr[i]);
		return integer;
	}

	private static char[] getPrimiryCharArray(String[] valStr) {
		char character[] = new char[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			character[i] = Character.valueOf(valStr[i].length() == 0 ? ' ' : valStr[i].charAt(0));
		return character;
	}

	private static Character[] getCharArray(String[] valStr) {
		Character character[] = new Character[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			character[i] = Character.valueOf(valStr[i].length() == 0 ? ' ' : valStr[i].charAt(0));
		return character;
	}

	private static byte[] getPrimiryByteArray(String[] valStr) {
		byte[] bytes = new byte[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			bytes[i] = Byte.valueOf(valStr[i]).byteValue();
		return bytes;
	}

	private static Byte[] getByteArray(String[] valStr) {
		Byte[] bytes = new Byte[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			bytes[i] = Byte.valueOf(valStr[i]);
		return bytes;
	}

	private static boolean[] getPrimiryBoolArray(String[] valStr) {
		boolean[] ret = new boolean[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			ret[i] = richBoolean(valStr[i]).booleanValue();
		return ret;
	}

	private static Boolean[] getBoolArray(String[] valStr) {
		Boolean[] ret = new Boolean[valStr.length];
		for (int i = 0; i < valStr.length; i++)
			ret[i] = richBoolean(valStr[i]);
		return ret;
	}

	public static Boolean richBoolean(String s) {
		if (s == null)
			return Boolean.FALSE;

		if ("true".equals(s))
			return Boolean.TRUE;
		if ("1".equals(s))
			return Boolean.TRUE;
		if ("yes".equals(s))
			return Boolean.TRUE;
		if ("on".equals(s))
			return Boolean.TRUE;
		if ("ok".equals(s))
			return Boolean.TRUE;

		return Boolean.FALSE;
	}
}
